/* 
 * Enterprise Library Extensions - DI + ORM.
 * Copyright (C) 2006
 *
 * GNU General Public License
 *
 * This program is free software; you can redistribute 
 * it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 */

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Design;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Reflection;

namespace ELE.EnterpriseLibrary.Common.Configuration.Design
{
  /// <summary>
  /// <para>This class is an editor for selecting an assembly from a list of loaded assemblies.
  /// Assemblies can be loaded from the GAC or a specific location.</para>
  /// <para>This class is used in conjuction with the <see cref="AssemblySelectorUI"/>.</para>
  /// <para>To use it, markup the property to be edited with the attribute
  ///   <code>
  ///    [System.ComponentModel.Editor(typeof(AssemblySelectorEditor), typeof(UITypeEditor))]
  ///   </code>
  /// </para>
  /// </summary>
  [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
  public class AssemblySelectorEditor : UITypeEditor
  {
    /// <summary>
    /// Default constructor
    /// </summary>
    public AssemblySelectorEditor()
      : base()
    {
    }
    /// <summary>
    /// Edits the value of the property that has been marked with the <see cref="System.ComponentModel.EditorAttribute"/> as
    /// using the AssemblySelectorEditor by poping up a window of <see cref="AssemblySelectorUI"/>.
    /// </summary>
    /// <param name="context">The context under which the component to be edited lives</param>
    /// <param name="provider">The service provider used to get the <see cref="IWindowsFormsEditorService"/></param>
    /// <param name="value">The value of the property to be edited</param>
    /// <returns>The edited property value</returns>
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
      Debug.Assert(provider != null, "No service provider; we cannot edit the value");
      if (provider != null)
      {
        IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

        Debug.Assert(edSvc != null, "No editor service; we cannot edit the value");
        if (edSvc != null)
        {

          IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
          Assembly currentType = null;
          if (value != null)
          {
            if (value is Assembly)
            {
              currentType = (Assembly)value;
            }
            else
            {
              currentType = Assembly.Load(value.ToString());
            }
          }
          using (AssemblySelectorUI form = new AssemblySelectorUI())
          {
            if (service.ShowDialog(form) == DialogResult.OK)
            {
              if (form.SelectedAssembly != null)
              {
                currentType = form.SelectedAssembly;
              }
            }
          }
          return currentType;
        }
      }
      return value;
    }
    /// <summary>
    /// Sets the edit style to <see cref="UITypeEditorEditStyle.Modal"/>
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
      return UITypeEditorEditStyle.Modal;
    }
     
  }
}
